モバイルアプリサービス開発で扱う認証情報管理のベストプラクティス
我々が扱う認証情報
モバイルアプリやサーバーアプリを開発したり運用したりする上で、私たちは重要な認証情報を数多く扱います。また受託開発の場合は、お客様にとってかなり重要な情報資産を扱うことや、複数のお客様の情報を扱うこともあります。このような状況の中で、我々は様々な認証情報を安全に管理しながら、迅速に開発を行わなければいけません。
ここでは、私なりの認証情報の扱い方を書き記します。
GitHub
GitHub自体の安全性
ソースコード管理にGitHubを利用する場合、GitHubが推奨するセキィリティ対策を取っていれば、基本的には安全に利用できるはずです。
GitHubが実施しているセキュリティ施策は下記にまとめられています。時間のあるときに見ておくようにしましょう。
また、脆弱性を探し出す方法はBug Bounty Hunterを募ってリーダーボード形式で評価するゲーミフィケーション方式を取っています。活発です。
リポジトリに認証情報を含めて良いか
安全に利用できる前提であれば、認証情報をリポジトリに置いて良いのでは?という考えもあるが、これについてはリポジトリに置くべきではないと思っています。
これは、そのリポジトリのソースコード自体がパブリックに漏洩する危険性という話ではなく、ソースコードの取り扱い方によっては、他者へ漏洩する危険性や不用意に複製される可能性があるからです。例えば下記のような話はよくあり得る話ですし、制限するのも困難なことです。
- 新しい案件で開発するアプリの機能は別案件で実装したことがあるので、ソースコードを貰っておき、それをベースに開発を進める。
- 案件への参画が終わった後でもローカルにクローンしてきたリポジトリを削除せずにずっと保持している。
- 開発環境、ステージング環境、本番環境にソースコードをまるっとそのままデプロイしている。
以上のことから、認証情報はリポジトリのソースコードに含めない形で管理することを推奨します。
AWS
AWS CLIを呼ぶとき
開発時にはローカルでAWS CLI経由でAPIを実行する必要性が出てきますが、これは開発用のIAM Userを作って ~/.aws/credentials
に設定して使います。
認証情報 (アクセスキーとシークレットキー) は、基本的には ~/.aws/credentials
に書くようになるため、誤ってGitにPushしちゃった、という事態は発生しません。
また、各AWSアカウントへのアクセスはAssumeRoleを使ってSwitch Role先の一時的な認証情報を得て実行するというフローがベストです。
- IAM ロールの切り替え(AWS Command Line Interface) - AWS Identity and Access Management
- IAM ロールの切り替え(API) - AWS Identity and Access Management
MFAを適用している場合はシェルスクリプトないしは公開されているツールを使って、一時的な認証情報を環境変数に展開する方法がオススメです。
direnv や dotenv などを使う場合
ディレクトリ単位で環境変数を自動的に変更できるdirenvやdotenv、 dotfilesなどがあります。
AWSの認証情報も載せたいところですが、リスクが大きいのでAWSの認証情報は扱わないようにすることを推奨します。理由は、GitにPushしてしまう事故が起きやすいためです。
direnvとdotenvを使う場合は、リポジトリ作成時に必ず.gitignore
に記載するようにしましょう。
CIサービスからデプロイするとき
Circle CIやTravis CIなどのようなCIサービスを使う場合、デプロイも自動化(CD)していることが多いかと思います。そのような場合、CIサービス上で動作するコンテナがAWSのリソース(EC2、ECS、CodeDeploy、S3、Elastic Beanstalk、CloudFormationなど)へのアクセス権を持つ必要があります。
これについては Administrator Accessを許可するIAM Userの利用は絶対に避け、デプロイ用のIAM Userを作成し、必要なアクションだけ許可するポリシーを組むようにします。これにはIAMへの知識が必要ですが、AWSを使う上で非常に重要なサービスなので覚えておきましょう。
アクセスキー、シークレットキーはCircle CIでもTravis CIでも暗号化した上で使えるようにする機能があるので、これを使うようにします。
- Continuous Deployment with AWS CodeDeploy - CircleCI
- ジョブ設定で環境変数をセット可能 (シークレット扱い)
- Encryption keys - Travis CI
- Travis CI 側で複合化可能なハッシュを
.travis.yml
で使用
- Travis CI 側で複合化可能なハッシュを
さらに、より安全に認証情報を渡すため利用先のAWSアカウントに配置したIAM RoleへのAssumeRoleのみを許可するIAM Userを使う方法もオススメです。これを実施することにより、CI(またはCD)の実行中に一時的な認証情報が使われる形になります。一時的な認証情報は有効期限が付いているので、万が一認証情報が流出してしまっても、永続的に悪用されることが無くなります。
iOS
開発用のDistributionの認証情報
開発用のDistributionの認証情報については、エラーが出てうまくアーカイブできない事象が発生しているのをよく見かけます。これはXcodeのFix Issueで解決しようとしているうちに知らぬ間に自動でRevokeしてしまう、というようなことに起因したりします。
毎度毎度その場でやりくりするのではなく、開発用のDistributionのp12ファイルを共有可能な場所に格納し、そこからダウンロードするというフローに統一した方が良いと思います。
本番用のDistributionの認証情報
これは非常に重要な認証情報です。特に受託開発でお客様に代わってビルドやアーカイブを行う場合、かなり神経を使った方が良いです。
リリース作業を代行する場合は、お客様からApple Developerアカウントに招待いただくか、p12ファイルを提供していただく方法があります。
自社のアプリの場合でも代行する場合でも、認証情報を誰のどのMacに入れているか、プロジェクトリーダーないし専任者が把握し、適切に管理する必要があります。必要がなくなったタイミングで直ちに削除しておくべきです。
また、CIサービス(最近では Bitrizeなどが有名)でアーカイブまで(さらにはサブミットまで)してしまおうという話もあります。最近のCIサービスはほとんどコンテナで動いている方式になっていますが、ある意味、自分たちが管理しているものではないシステムに認証情報を渡すことになります。これに違和感を覚えるお客様も居ると思います。勝手に採用せず、お客様に話をした上で必ず了承をもらうようにしましょう。
リリース作業の頻度がさほど高くない場合は、手動でやってしまう方が早いし確実な場合があります。
Remote Notificationの認証情報
Remote Notificationについては、トークンによる認証がサポートされました。Firebase Cloud Messagingなどは、こちらの方法をすでにサポート済みだったりします。p12ファイルで行なう場合と異なり、期限が切れるたびに新しいp12ファイルを用意しなければいけない手間が省けます。利用できる場合は積極的に利用しましょう。
Android
Google Play Storeアップロード用のapkを作るためのキーストア
キーストアは、Google Play Storeアップロード用のものは一度作ったら二度と同じものを作れない特徴があります。そのため、アップロードまで行った場合は キーストアは絶対に消してはいけません。アップデートできなくなります。
開発用途のキーストアはソースコードのリポジトリ内で管理しても特に問題はありませんが、リリース用途のキーストアはリポジトリ外で管理すべきです。これはサーバーサイド、iOS アプリとほぼ同じ理由ですが、簡単に複製ができる場所に置くべきではないからです。
AWSを利用している場合はS3に置き、必要なクライアントからAWSの認証情報を使ってダウンロードするのが良いと思います。
まとめ
これまでモバイルアプリサービス開発案件に携わる中で、あくまで主観で、認証情報をどう管理すべきか書いてみました。総じて言えるのは安心するレベルまで保護しつつ、スピーディに開発するということです。スピード重視だからといって保護しなすぎるとセキュリティリスクを伴いますし、信頼も失います。その一方、保護しようと思えばいくらでも保護できますが、開発効率は絶対に落ちます。案件ごとにうまく折り合いを付けましょう。
本記事で書いている内容に誤りがある場合は、ぜひコメントにてご報告いただければと思います。また「ウチではこのツールを使ってるよ!」「この方法もオススメだよ!」などといったアドバイスも大歓迎です!